﻿using DevExpress.Xpo.Logger;
using EyFramework.Common;
using NLog;
using System;
using System.Runtime.InteropServices;
using YbService.Entity;

namespace InsuService
{
    public class ICReader
    {
        public static readonly NLog.Logger logger = NLog.LogManager.GetLogger("IC_READ");

        #region 从ICCInter_HZ.DLL文件中到处接口函数

        /// <summary>
        /// 应用系统卡交易处理入口
        /// 交易代码:
        /// 1101	读医疗保险基本信息（须PIN验证）	医保日常使用
        /// 1103	读卡片基本信息	医院医生工作站使用
        /// </summary>
        /// <param name="TransNum">交易代码</param>
        /// <param name="DataIn">输入数据字符串</param>
        /// <param name="DataOut">输出数据字符串，注意分配足够存储空间</param>
        /// <returns> =0 －成功。小于0	－	错误（见错误代码定义表）</returns>
        [DllImport("ICCInter_HZ.DLL", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        private static extern int ICC_Transaction(int TransNum,
                                                    [MarshalAs(UnmanagedType.LPArray)] byte[] DataIn,
                                                    [MarshalAs(UnmanagedType.LPArray)] byte[] DataOut);

        [DllImport("ICCInter_HZ.DLL", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        private static extern int ICC_Face_detect_init();

        [DllImport("ICCInter_HZ.DLL", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        private static extern int ICC_Face_detect_destory();

        /// <summary>
        /// 获取电子凭证医保信息获取
        /// </summary>
        /// <returns></returns>
        [DllImport("ICCInter_HZ.DLL", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        private static extern int ICC_GetDZPZ_Info([MarshalAs(UnmanagedType.LPArray)] byte[] DataIn,
                                                    [MarshalAs(UnmanagedType.LPArray)] byte[] DataOut);

        #endregion 从ICCInter_HZ.DLL文件中到处接口函数

        #region 代码定义

        /// <summary>
        /// 以下交易，会自动打开和关闭端口
        /// </summary>
        public enum enum_读卡方式
        {
            读卡片基本信息_须PIN验证_1111 = 1111,
            读卡片基本信息_无须PIN验证_1113 = 1113,
            扫码获取卡片基本信息_无须PIN验证_1115 = 1115,
            获取卡片基本信息_无须PIN验证_1116 = 1116,
            获取卡片基本信息_无须PIN验证_卡令牌_1118 = 1118,
            扫脸获取卡片基本信息_无须PIN验证_1119 = 1119,
            扫电子凭证获取卡信息_1125 = 1125
        }

        public enum enum_错误定义
        {
            IFD_OK_正常 = 0,
            IFD_ICC_Type_Error_卡片类型不对 = -1,
            IFD_NO_ICC_卡尚未插入 = -2,
            IFD_ICC_ON_卡尚未取出 = -3,
            IFD_ICC_NO_Response_卡片无应答 = -4,
            IFD_Error_接口设备故障 = -5,
            IFD_Bad_Command_不支持该命令 = -6,
            IFD_Length_Error_命令长度错误 = -7,
            IFD_Parameter_Error_命令参数错误 = -8,
            IFD_Access_Deny_访问权限不满足 = -9,
            IFD_CheckSum_Error_信息校验和出错 = -10,
            IFD_NOT_SAMECARD_检查是否为同一张卡 = -21,
            IFD_NOT_HZCARD_非正式的杭州市市民卡 = -22,
            IFD_NOT_KEYBACK_不输入密码, 直接退出交易 = -23,
            IFD_KEYERROR_ONE_密码认证失败只允许一次出错机会 = -31,
            IFD_KEYERROR_TWO_密码认证失败只允许两次出错机会 = -32,
            IFD_KEYERROR_THREE_密码认证失败只允许三次出错机会 = -33,
            IFD_KEYERROR_FOUR_密码认证失败只允许四次出错机会 = -34,
            IFD_KEYERROR_FIVE_密码认证失败只允许五次出错机会 = -35,
            S_PINBLOCKED_PIN已经锁定 = -42,
            IFD_GET_QRCODE_ERROR_获取二维码失败 = -37,
            IFD_SOCKET_ERROR_网络交互失败 = -38,
            IFD_NO_CUSTOMER_INFO_人员信息不存在 = -39,
            IFD_QRCODE_INVALID_二维码失效 = -50,
            IFD_CALL_ALIPAY_FAILED_支付宝验证失败 = -60,
            IFD_CARDSTAT_ERROR_卡信息异常 = -61,
            IFD_NO_BINDING_RECORD_无绑卡记录 = -62,
            IFD_KG_SYS_ABNORMAL_卡管系统异常 = -63,
            IFD_GET_ALIFACE_DEV_ERROR_刷脸设备信息获取异常 = -70,
            IFD_ALIFACE_DEV_ERROR_刷脸失败 = -71,
            IFD_INIT_FACE_SDK_ERROR_刷脸初始化异常 = -72,
            IFD_DETECT_FACE_ERROR_人脸检测失败 = -73,
            IFD_DETECT_FACE_TIMEOUT_人脸检测超时 = -74,
            IFD_KG_UNKNOW_CODE_卡管服务器返回未知错误码 = -99,
            S_DLLERR_动态库加载错误 = -101,
            S_TRANSIDERROR_交易代码错误 = -102,
            S_INTERNALERR_内部命令错误 = -999,
            S_PSAMERR_PSAM操作错误 = -2001
        }

        #endregion 代码定义

        #region 参数

        /// <summary>
        /// 输入数据字符串
        /// </summary>
        private byte[] bDataIn = new byte[1024];

        public string DataIn
        {
            get { return System.Text.Encoding.Default.GetString(bDataIn); }
            set { bDataIn = System.Text.Encoding.Default.GetBytes(value); }
        }

        /// <summary>
        /// 输出数据字符串
        /// </summary>
        private byte[] bDataOut = new byte[1024];

        public string DataOut
        {
            get { return System.Text.Encoding.Default.GetString(bDataOut); }
            set { bDataOut = System.Text.Encoding.Default.GetBytes(value); }
        }

        private string p_ErrText = "";
        public string _ErrText { get { return p_ErrText; } }

        #endregion 参数

        public CardFormat ReadIC(enum_读卡方式 enum读卡方式, string v_Password)
        {
            if (enum读卡方式 == enum_读卡方式.扫脸获取卡片基本信息_无须PIN验证_1119)
            {
                ICC_Face_detect_init();
            }
            DataIn = v_Password;
            if (enum读卡方式 == enum_读卡方式.获取卡片基本信息_无须PIN验证_1116 || enum读卡方式 == enum_读卡方式.获取卡片基本信息_无须PIN验证_卡令牌_1118)
            {
                DataIn = DataIn + "|";
            }
            int i = ICC_Transaction((int)enum读卡方式, bDataIn, bDataOut);
            if (i < 0)
            {
                logger.Debug("市民卡芯片读取完毕，读取结果:{0},读取失败", i);
                p_ErrText = ((enum_错误定义)i).ToString();
                Exception ee = new Exception("读市民卡错误 - " + _ErrText + ",bDataIn=" + DataIn);
                throw ee;
            }

            CardFormat data = new CardFormat(DataOut);
            logger.Debug("市民卡芯片读取完毕，读取结果:{0},读取内容:{1}", i, DataOut);
            if (enum读卡方式 == enum_读卡方式.扫脸获取卡片基本信息_无须PIN验证_1119)
            {
                ICC_Face_detect_destory();
            }
            return data;
        }

        public DzpzInfo GetDzpzInfo(string token)
        {
            DataIn = token;
            int i = ICC_GetDZPZ_Info(bDataIn, bDataOut);
            if (i < 0)
            {
                p_ErrText = ((enum_错误定义)i).ToString();
                Exception ee = new Exception("获取电子凭证信息错误 - " + _ErrText);
                throw ee;
            }
            return new DzpzInfo(DataOut);
        }
    }
}